Platform Explorer / Nuxeo Platform 2023.18

Component org.nuxeo.ecm.directory.ldap.LDAPDirectoryFactory

Documentation

The LDAPDirectoryFactory component provides implementation of the Directory API using an external LDAP server as storage backend, typically to fetch users and groups data check password based authentication.

Requirements

Resolution Order

799
The resolution order represents the order in which this component has been resolved by the Nuxeo Runtime framework.
You can influence this order by adding "require" tags in your component declaration, to make sure it is resolved after another component.

Start Order

832
The start order represents the order in which this component has been started by the Nuxeo Runtime framework.
This number is interesting to tweak if your Java component interacts with other components, and needs to be started before or after another one.
It can be changed by implementing the method "Component#getApplicationStartedOrder()" on your Java component: components are sorted according to this reference value, in increasing order.
The default value is 1000, and the repository initialization uses number 100. Negative values can also be used.

Implementation

Class: org.nuxeo.ecm.directory.ldap.LDAPDirectoryFactory

Services

Extension Points

XML Source

<?xml version='1.0' encoding='UTF-8'?>
<component name="org.nuxeo.ecm.directory.ldap.LDAPDirectoryFactory">

  <require>org.nuxeo.ecm.directory.DirectoryServiceImpl</require>

  <documentation>
    The LDAPDirectoryFactory component provides implementation of the
    Directory API using an external LDAP server as storage backend,
    typically to fetch users and groups data check password based
    authentication.

    @author Olivier Grisel (ogrisel@nuxeo.com)
  </documentation>

  <implementation class="org.nuxeo.ecm.directory.ldap.LDAPDirectoryFactory"/>

  <service>
    <provide interface="org.nuxeo.ecm.directory.ldap.LDAPDirectoryFactory"/>
  </service>

  <extension-point name="servers">
    <documentation>
      The servers extension point is used to register network connection
      parameters to a pool of LDAP servers.

      Examples:

      <code>
        <server name="default">
          <ldapUrl>ldap://localhost:389</ldapUrl>
          <ldapUrl>ldap://server2:389</ldapUrl>
          <ldapUrl>ldaps://server3:389</ldapUrl>

          <!-- LDAP SRV DNS resolution on _ldap._tcp.example.com -->
          <ldapUrl>ldap:///dc=example,dc=com</ldapUrl>

          <!-- LDAP SRV DNS resolution on _gc._tcp.example.com -->
          <ldapUrl srvPrefix="_gc._tcp">ldap:///dc=example,dc=com</ldapUrl>

          <connectionTimeout>10000</connectionTimeout>
          <retries>5</retries>

          <poolingEnabled>true</poolingEnabled>
          <poolingConnectionTimeout>60000</poolingConnectionTimeout>
          <verifyServerCert>true</verifyServerCert>

          <bindDn>cn=nuxeo5,ou=applications,dc=example,dc=com</bindDn>
          <bindPassword>********</bindPassword>
        </server>
      </code>

      The ldapUrl tags point to server (IP address or DNS name) and
      ports. If more than one is provided, the Nuxeo EP will use a pool
      of load balanced connections to each server. They are assumed to
      be replicated versions of a master server that should belong to
      the list.

      The connectionTimeout element specifies a connection timeout in milliseconds.
      The default is 10000.

      The retries element indicates how many times the request will be retried
      if LDAP server returns a ServiceUnavailableException. The default is 5.

      The poolingEnabled element specifies whether to use LDAP connection pooling.
      The default is true.

      The poolingTimeout element specifies, in milliseconds, how long a connection
      may remain in the pool when LDAP connection pooling is enabled.
      The default is 60000.

      The verifyServerCert element specifies whether, in SSL mode, all certificates
      should be checked. This should only be disabled when testing with test server
      having self-signed certificates. The default is true.

      The bindDn and bindPassword credentials are used by Nuxeo EP to
      access the content of the LDAP servers. It should have the read
      permission to any entry that is to be used by Nuxeo EP and write
      right to branches were Nuxeo EP is supposed to create or edit
      entries.

      For instance, in OpenLDAP you should have ACLs such as:

      <code>
        access to attrs="userPassword"
        by dn="cn=ldapadmin,dc=example,dc=com" write
        by dn="cn=nuxeo5,ou=applications,dc=example,dc=com" write
        by anonymous auth
        by self write
        by * none

        access to dn.base="" by * read

        # nuxeo5 can manage the ou=people branch
        access to dn.subtree="ou=people,dc=example,dc=com"
        by dn="cn=nuxeo5,ou=applications,dc=example,dc=com" write
        by users read
        by self write
        by * none

        access to dn.subtree="ou=groups,dc=example,dc=com"
        by dn="cn=nuxeo5,ou=applications,dc=example,dc=com" write
        by users read
        by self write
        by * none

        # The admin dn has full write access
        # other
        access to *
        by dn="cn=ldapadmin,dc=example,dc=com" write
        by users read
        by * none
      </code>

      User authentication is done using a bind method against the user
      provided login and password from the login form and not the bindDn
      / bindPassword credentials.
    </documentation>

    <object class="org.nuxeo.ecm.directory.ldap.LDAPServerDescriptor"/>
  </extension-point>

  <extension-point name="directories">
    <documentation>
      The directories extension point is used to register LDAP filtering
      parameters to identify which part of the LDAP branches are actually
      used by Nuxeo EP to fetch its entries.

      Examples:

      <code>
        <directory name="userDirectory">
          <server>default</server>
          <schema>user</schema>
          <types>
            <type>system</type>
          </types>
          <idField>username</idField>
          <idCase>unchanged</idCase>
          <passwordField>password</passwordField>
          <passwordHashAlgorithm>SSHA</passwordHashAlgorithm>
          <searchBaseDn>ou=people,dc=example,dc=com</searchBaseDn>
          <searchClass>person</searchClass>
          <searchFilter>(&amp;(sn=toto*)(myCustomAttribute=somevalue))</searchFilter>
          <searchScope>onelevel</searchScope>

          <readOnly>false</readOnly>

          <cacheTimeout>3600</cacheTimeout>
          <cacheMaxSize>1000</cacheMaxSize>

          <creationBaseDn>ou=people,dc=example,dc=com</creationBaseDn>
          <creationClass>top</creationClass>
          <creationClass>person</creationClass>
          <creationClass>organizationalPerson</creationClass>
          <creationClass>inetOrgPerson</creationClass>
          <rdnAttribute>uid</rdnAttribute>

          <querySizeLimit>200</querySizeLimit>
          <queryTimeLimit>0</queryTimeLimit>

          <fieldMapping name="username">uid</fieldMapping>
          <fieldMapping name="password">********</fieldMapping>
          <fieldMapping name="firstName">givenName</fieldMapping>
          <fieldMapping name="lastName">sn</fieldMapping>
          <fieldMapping name="company">o</fieldMapping>
          <fieldMapping name="email">mail</fieldMapping>

          <references>
            <inverseReference field="groups" directory="groupDirectory" dualReferenceField="members"/>
          </references>
        </directory>

        <directory name="groupDirectory">
          <server>default</server>
          <schema>group</schema>
          <idField>groupname</idField>
          <searchBaseDn>ou=groups,dc=example,dc=com</searchBaseDn>
          <searchFilter>(|(objectClass=groupOfUniqueNames)(objectClass=groupOfURLs))</searchFilter>
          <searchScope>subtree</searchScope>

          <!-- Special entry adaptor that makes entries in the ou=editable branch editable
          other entries have the readonly flag. This require adding a "dn" xs:string field
          to the group schema.
          -->
        <entryAdaptor class="org.nuxeo.ecm.directory.impl.WritePolicyEntryAdaptor">
          <parameter name="fieldName">dn</parameter>
          <parameter name="regexp">.*,ou=editable,ou=groups,dc=example,dc=com</parameter>
        </entryAdaptor>

          <readOnly>false</readOnly>

          <cacheTimeout>3600</cacheTimeout>
          <cacheMaxSize>1000</cacheMaxSize>

          <creationBaseDn>ou=editable,ou=groups,dc=example,dc=com</creationBaseDn>
          <creationClass>top</creationClass>
          <creationClass>groupOfUniqueNames</creationClass>
          <rdnAttribute>cn</rdnAttribute>

          <querySizeLimit>200</querySizeLimit>
          <queryTimeLimit>0</queryTimeLimit>

          <fieldMapping name="groupname">cn</fieldMapping>

          <references>
            <!-- LDAP reference resolve DNs embedded in uniqueMember attributes

              If the target directory has no specific filtering policy, it is most
              of the time not necessary to enable the 'forceDnConsistencyCheck' policy.

              Enabling this option will fetch each reference entry to ensure its
              existence in the target directory.
            -->
            <ldapReference field="members" directory="userDirectory" forceDnConsistencyCheck="false" staticAttributeIdIsDn="true" staticAttributeId="uniqueMember" dynamicAttributeId="memberURL"/>

            <ldapReference field="subGroups" directory="groupDirectory" forceDnConsistencyCheck="false" staticAttributeId="uniqueMember" dynamicAttributeId="memberURL"/>

            <inverseReference field="parentGroups" directory="groupDirectory" dualReferenceField="subGroups"/>

            <ldapTreeReference field="children" directory="groupDirectory" scope="onelevel"/>
            <inverseReference field="parents" directory="groupDirectory" dualReferenceField="children"/>

          </references>

        </directory>
      </code>

      In the previous examples we configured two directories one for the
      users and one for the groups of users. Each directory uses a
      single schema which is to be registered as any core document
      schema and that will be used to build a DocumentModel for each
      matching entry of the directory.


      Nuxeo EP provides group resolution for statically dn-referenced
      entries (in read and write mode) and for dynamically ldapUrl
      matched entries (readonly). You may also need to statically
      reference entries without a dn using the 'staticAttributeIdIsDn'
      attribute.

      The references tags are used to dynamically build nxs:stringList
      fields of that schema that are to compute membership relationships
      between users and groups or between parent groups and sub groups.
      It can also resole children and parents following the ldap tree
      structure.

      You have two ways for declaring a dynamic reference in a 'references' tag.
      You can use 'dynamicAttributeId' to point to an ldap attribute that
      contains an ldap url.

      <code>
      <ldapReference field="members" directory="userDirectory" dynamicAttributeId="memberURL"/>
      </code>

      Or, you can use a subtag 'dynamicReference' to declare attributes that
      contain a DN, a filter and a type. This values will be used to selected
      the references.

      <code>
      <ldapReference field="members" directory="userDirectory"/>
         <dynamicReference filter="ldapAttribute" type="subtree/onelevel" baseDN="ldapAttribute"/>
      <ldapReference/>
      </code>

      When using dynamic references, caching is advised since dynamic group
      resolution can be expensive.

      The element "idCase" makes it possible to control the case of the
      identifier on Nuxeo side. It accepts values "upper", "lower" or
      "unchanged". It is useful when changing case on the LDAP without affecting
      Nuxeo (for rights management for instance which is case sensitive for
      instance).


      Dependening on your LDAP Backend implementation, if you have some specific restriction
      (for example on password, or logins ...), you may want Nuxeo to handle the validation
      errors of your server on the Nuxeo side.

      Since there error code and message may vary  depending on the LDAP server provider, you
      may need to provide a custom class that knows how to handle the Exceptions returned by it.

      For this you can specify a class that will be in charge of this task.
      <code>
        <ldapExceptionHandler>org.nuxeo.ecm.directory.ldap.DefaultLdapExceptionProcessor</ldapExceptionHandler>
      </code>
      This class should implement org.nuxeo.ecm.directory.ldap.LdapExceptionProcessor and return
      a RecoverableClientException for any exception that should be displayed to the user.


      By default, referrals will be automatically resolved, if you don't want that behavior (since 5.9.4) you can use the followReferrals tag

      <code>
        <directory name="groupDirectory">
           ....
           <followReferrals>false</followReferrals>
           ...
        </directory>
      </code>

    </documentation>

    <object class="org.nuxeo.ecm.directory.ldap.LDAPDirectoryDescriptor"/>
  </extension-point>

</component>